#include "BlankScreenDetector.h"
#include "napi/native_api.h"
#include "qos/qos.h"
#include <hilog/log.h>

// 定义日志域和标签
#undef LOG_DOMAIN
#undef LOG_TAG
#define LOG_DOMAIN 0x3200
#define LOG_TAG "BlankDetector"

// 异步工作数据结构
struct AsyncWorkData {
    napi_async_work work;
    napi_deferred deferred;
    
    // 输入参数
    uint8_t* pixelData;
    size_t dataLength;
    int32_t width;
    int32_t height;
    int32_t bytesPerPixel;
    
    // 输出结果
    DetectionResult result;
    bool hasError;
    std::string errorMessage;
    
    AsyncWorkData() : work(nullptr), pixelData(nullptr), dataLength(0), 
                     width(0), height(0), bytesPerPixel(0), hasError(false) {}
};

// 创建HSV颜色对象的辅助函数
static napi_value CreateHSVColorObject(napi_env env, const HSVPixel& hsvColor) {
    napi_value hsvObj;
    napi_create_object(env, &hsvObj);
    
    napi_value h, s, v, a;
    napi_create_double(env, hsvColor.h, &h);
    napi_create_double(env, hsvColor.s, &s);
    napi_create_double(env, hsvColor.v, &v);
    napi_create_int32(env, hsvColor.a, &a);
    
    napi_set_named_property(env, hsvObj, "h", h);
    napi_set_named_property(env, hsvObj, "s", s);
    napi_set_named_property(env, hsvObj, "v", v);
    napi_set_named_property(env, hsvObj, "a", a);
    
    return hsvObj;
}

// 创建RGB颜色对象的辅助函数
static napi_value CreateRGBColorObject(napi_env env, const Pixel& rgbColor) {
    napi_value rgbObj;
    napi_create_object(env, &rgbObj);
    
    napi_value r, g, b, a;
    napi_create_int32(env, rgbColor.r, &r);
    napi_create_int32(env, rgbColor.g, &g);
    napi_create_int32(env, rgbColor.b, &b);
    napi_create_int32(env, rgbColor.a, &a);
    
    napi_set_named_property(env, rgbObj, "r", r);
    napi_set_named_property(env, rgbObj, "g", g);
    napi_set_named_property(env, rgbObj, "b", b);
    napi_set_named_property(env, rgbObj, "a", a);
    
    return rgbObj;
}

// 在工作线程中执行的函数
static void ExecuteWork(napi_env env, void* data) {
    AsyncWorkData* asyncData = static_cast<AsyncWorkData*>(data);
    
    // 设置 QoS 并打印结果
    int qosResult = OH_QoS_SetThreadQoS(QoS_Level::QOS_UTILITY);
    if (qosResult == 0) {
        OH_LOG_INFO(LOG_APP, "QoS set successfully to QOS_UTILITY level");
    } else {
        OH_LOG_ERROR(LOG_APP, "Failed to set QoS, error code: %{public}d", qosResult);
    }
    
    try {
        OH_LOG_INFO(LOG_APP, "Starting blank screen detection, image size: %{public}dx%{public}d, bytesPerPixel: %{public}d", 
                    asyncData->width, asyncData->height, asyncData->bytesPerPixel);
        
        auto _start_ = std::chrono::high_resolution_clock::now();
        // 执行检测
        BlankScreenDetector detector;
        asyncData->result = detector.detect(
            asyncData->pixelData, 
            asyncData->width, 
            asyncData->height, 
            asyncData->bytesPerPixel
        );
        asyncData->hasError = false;
        auto _end_ = std::chrono::high_resolution_clock::now();
        
        OH_LOG_INFO(LOG_APP, "Detection completed successfully, hasBlankScreen: %{public}s, overallBlankRatio: %{public}f, cost %{public}lld us", 
                    asyncData->result.hasBlankScreen ? "true" : "false", 
                    asyncData->result.overallBlankRatio,
        std::chrono::duration_cast<std::chrono::microseconds>(_end_ - _start_).count());
        
    } catch (const std::exception& e) {
        asyncData->hasError = true;
        asyncData->errorMessage = e.what();
        OH_LOG_ERROR(LOG_APP, "Detection failed with exception: %{public}s", e.what());
    } catch (...) {
        asyncData->hasError = true;
        asyncData->errorMessage = "Unknown error occurred during detection";
        OH_LOG_ERROR(LOG_APP, "Detection failed with unknown error");
    }
}

// 工作完成后在主线程中执行的函数
static void CompleteWork(napi_env env, napi_status status, void* data) {
    AsyncWorkData* asyncData = static_cast<AsyncWorkData*>(data);
    
    if (status != napi_ok || asyncData->hasError) {
        OH_LOG_ERROR(LOG_APP, "Async work completed with error, status: %{public}d, hasError: %{public}s", 
                     status, asyncData->hasError ? "true" : "false");
        
        // 创建错误对象
        napi_value error;
        napi_value errorMessage;
        napi_create_string_utf8(env, asyncData->errorMessage.c_str(), NAPI_AUTO_LENGTH, &errorMessage);
        napi_create_error(env, nullptr, errorMessage, &error);
        
        // 拒绝Promise
        napi_reject_deferred(env, asyncData->deferred, error);
    } else {
        OH_LOG_INFO(LOG_APP, "Async work completed successfully, building result object");
        
        // 构建返回对象
        napi_value resultObj;
        napi_create_object(env, &resultObj);
        
        // hasBlankScreen
        napi_value hasBlankScreen;
        napi_get_boolean(env, asyncData->result.hasBlankScreen, &hasBlankScreen);
        napi_set_named_property(env, resultObj, "hasBlankScreen", hasBlankScreen);
        
        // overallBlankRatio
        napi_value overallBlankRatio;
        napi_create_double(env, asyncData->result.overallBlankRatio, &overallBlankRatio);
        napi_set_named_property(env, resultObj, "overallBlankRatio", overallBlankRatio);
        
        // summary
        napi_value summary;
        napi_create_string_utf8(env, asyncData->result.summary.c_str(), NAPI_AUTO_LENGTH, &summary);
        napi_set_named_property(env, resultObj, "summary", summary);
        
        // blankRegions数组
        napi_value regionsArray;
        napi_create_array_with_length(env, asyncData->result.blankRegions.size(), &regionsArray);
        
        for (size_t i = 0; i < asyncData->result.blankRegions.size(); ++i) {
            const auto& region = asyncData->result.blankRegions[i];
            
            napi_value regionObj;
            napi_create_object(env, &regionObj);
            
            // bounds
            napi_value boundsObj;
            napi_create_object(env, &boundsObj);
            
            napi_value x, y, w, h;
            napi_create_int32(env, region.bounds.x, &x);
            napi_create_int32(env, region.bounds.y, &y);
            napi_create_int32(env, region.bounds.width, &w);
            napi_create_int32(env, region.bounds.height, &h);
            
            napi_set_named_property(env, boundsObj, "x", x);
            napi_set_named_property(env, boundsObj, "y", y);
            napi_set_named_property(env, boundsObj, "width", w);
            napi_set_named_property(env, boundsObj, "height", h);
            
            napi_set_named_property(env, regionObj, "bounds", boundsObj);
            
            // type
            napi_value type;
            napi_create_int32(env, static_cast<int>(region.type), &type);
            napi_set_named_property(env, regionObj, "type", type);
            
            // confidence
            napi_value confidence;
            napi_create_double(env, region.confidence, &confidence);
            napi_set_named_property(env, regionObj, "confidence", confidence);
            
            // uniformity
            napi_value uniformity;
            napi_create_double(env, region.uniformity, &uniformity);
            napi_set_named_property(env, regionObj, "uniformity", uniformity);
            
            // description
            napi_value description;
            napi_create_string_utf8(env, region.description.c_str(), NAPI_AUTO_LENGTH, &description);
            napi_set_named_property(env, regionObj, "description", description);
            
            // dominantColor (RGB格式，保持兼容性)
            napi_value rgbColorObj = CreateRGBColorObject(env, region.dominantColor);
            napi_set_named_property(env, regionObj, "dominantColor", rgbColorObj);
            
            // dominantColorHSV (新增HSV格式)
            napi_value hsvColorObj = CreateHSVColorObject(env, region.dominantColorHSV);
            napi_set_named_property(env, regionObj, "dominantColorHSV", hsvColorObj);
            
            napi_set_element(env, regionsArray, i, regionObj);
        }
        
        napi_set_named_property(env, resultObj, "blankRegions", regionsArray);
        
        // stats统计信息
        napi_value statsObj;
        napi_create_object(env, &statsObj);
        
        napi_value totalWhiteRegions, totalBlackRegions, totalSolidColorRegions, largestRegionArea, averageRegionSize;
        napi_create_int32(env, asyncData->result.stats.totalWhiteRegions, &totalWhiteRegions);
        napi_create_int32(env, asyncData->result.stats.totalBlackRegions, &totalBlackRegions);
        napi_create_int32(env, asyncData->result.stats.totalSolidColorRegions, &totalSolidColorRegions);
        napi_create_int32(env, asyncData->result.stats.largestRegionArea, &largestRegionArea);
        napi_create_double(env, asyncData->result.stats.averageRegionSize, &averageRegionSize);
        
        napi_set_named_property(env, statsObj, "totalWhiteRegions", totalWhiteRegions);
        napi_set_named_property(env, statsObj, "totalBlackRegions", totalBlackRegions);
        napi_set_named_property(env, statsObj, "totalSolidColorRegions", totalSolidColorRegions);
        napi_set_named_property(env, statsObj, "largestRegionArea", largestRegionArea);
        napi_set_named_property(env, statsObj, "averageRegionSize", averageRegionSize);
        
        // dominantColors数组 (RGB格式，保持兼容性)
        napi_value dominantColorsArray;
        napi_create_array_with_length(env, asyncData->result.stats.dominantColors.size(), &dominantColorsArray);
        
        for (size_t i = 0; i < asyncData->result.stats.dominantColors.size(); ++i) {
            const auto& color = asyncData->result.stats.dominantColors[i];
            napi_value colorObj = CreateRGBColorObject(env, color);
            napi_set_element(env, dominantColorsArray, i, colorObj);
        }
        
        napi_set_named_property(env, statsObj, "dominantColors", dominantColorsArray);
        
        // dominantColorsHSV数组 (新增HSV格式)
        napi_value dominantColorsHSVArray;
        napi_create_array_with_length(env, asyncData->result.stats.dominantColorsHSV.size(), &dominantColorsHSVArray);
        
        for (size_t i = 0; i < asyncData->result.stats.dominantColorsHSV.size(); ++i) {
            const auto& hsvColor = asyncData->result.stats.dominantColorsHSV[i];
            napi_value hsvColorObj = CreateHSVColorObject(env, hsvColor);
            napi_set_element(env, dominantColorsHSVArray, i, hsvColorObj);
        }
        
        napi_set_named_property(env, statsObj, "dominantColorsHSV", dominantColorsHSVArray);
        napi_set_named_property(env, resultObj, "stats", statsObj);
        
        // 解决Promise
        napi_resolve_deferred(env, asyncData->deferred, resultObj);
        
        OH_LOG_INFO(LOG_APP, "Result object created and promise resolved successfully with HSV color support");
    }
    
    // 清理资源
    napi_delete_async_work(env, asyncData->work);
    delete[] asyncData->pixelData;
    delete asyncData;
}

// 辅助函数：创建并拒绝 Promise
static napi_value RejectWithError(napi_env env, const char* errorMessage) {
    napi_value promise;
    napi_deferred deferred;
    napi_create_promise(env, &deferred, &promise);
    
    napi_value error;
    napi_value errorMsg;
    napi_create_string_utf8(env, errorMessage, NAPI_AUTO_LENGTH, &errorMsg);
    napi_create_error(env, nullptr, errorMsg, &error);
    napi_reject_deferred(env, deferred, error);
    
    OH_LOG_ERROR(LOG_APP, "DetectBlankScreenAsync rejected: %{public}s", errorMessage);
    return promise;
}

// 异步检测函数
static napi_value DetectBlankScreenAsync(napi_env env, napi_callback_info info) {
    size_t argc = 4;
    napi_value args[4] = {nullptr};
    
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    
    if (argc < 4) {
        OH_LOG_ERROR(LOG_APP, "DetectBlankScreenAsync: Wrong number of arguments, expected 4, got %{public}zu", argc);
        napi_throw_error(env, nullptr, "Wrong number of arguments");
        return nullptr;
    }
    
    OH_LOG_INFO(LOG_APP, "DetectBlankScreenAsync called with %{public}zu arguments", argc);
    
    // ===== 参数类型验证 =====
    napi_valuetype argTypes[4];
    for (int i = 0; i < 4; i++) {
        napi_typeof(env, args[i], &argTypes[i]);
    }
    
    // 验证第一个参数是 ArrayBuffer
    bool isArrayBuffer = false;
    napi_is_arraybuffer(env, args[0], &isArrayBuffer);
    if (!isArrayBuffer) {
        return RejectWithError(env, "First argument must be an ArrayBuffer");
    }
    
    // 验证数值参数
    if (argTypes[1] != napi_number || argTypes[2] != napi_number || argTypes[3] != napi_number) {
        return RejectWithError(env, "width, height, and bytesPerPixel must be numbers");
    }
    
    // ===== 获取参数值 =====
    void* pixelData = nullptr;
    size_t dataLength = 0;
    napi_get_arraybuffer_info(env, args[0], &pixelData, &dataLength);
    
    int32_t width = 0, height = 0, bytesPerPixel = 0;
    napi_get_value_int32(env, args[1], &width);
    napi_get_value_int32(env, args[2], &height);
    napi_get_value_int32(env, args[3], &bytesPerPixel);
    
    // ===== 参数合法性验证 =====
    if (pixelData == nullptr) {
        return RejectWithError(env, "ArrayBuffer data is null");
    }
    
    if (width <= 0 || height <= 0) {
        return RejectWithError(env, "width and height must be positive");
    }
    
    if (bytesPerPixel < 3 || bytesPerPixel > 4) {
        return RejectWithError(env, "bytesPerPixel must be 3 or 4");
    }
    
    // 防止整数溢出：先检查乘法是否会溢出
    constexpr int64_t MAX_PIXELS = 100000000LL; // 1亿像素上限（约10000x10000）
    int64_t totalPixels = static_cast<int64_t>(width) * static_cast<int64_t>(height);
    if (totalPixels > MAX_PIXELS) {
        return RejectWithError(env, "Image too large (exceeds 100M pixels)");
    }
    
    // 验证缓冲区大小
    size_t expectedSize = static_cast<size_t>(totalPixels) * static_cast<size_t>(bytesPerPixel);
    if (dataLength < expectedSize) {
        OH_LOG_ERROR(LOG_APP, "Buffer size mismatch: expected %{public}zu, got %{public}zu", expectedSize, dataLength);
        return RejectWithError(env, "ArrayBuffer size is smaller than expected (width * height * bytesPerPixel)");
    }
    
    OH_LOG_INFO(LOG_APP, "Parameters validated - width: %{public}d, height: %{public}d, bytesPerPixel: %{public}d, dataLength: %{public}zu, expectedSize: %{public}zu", 
                width, height, bytesPerPixel, dataLength, expectedSize);
    
    // ===== 创建 Promise 和异步工作 =====
    napi_value promise;
    napi_deferred deferred;
    napi_create_promise(env, &deferred, &promise);
    
    AsyncWorkData* asyncData = new AsyncWorkData();
    asyncData->deferred = deferred;
    asyncData->width = width;
    asyncData->height = height;
    asyncData->bytesPerPixel = bytesPerPixel;
    asyncData->dataLength = expectedSize; // 使用预期大小，不要超出
    
    // 复制像素数据到堆内存
    asyncData->pixelData = new uint8_t[expectedSize];
    memcpy(asyncData->pixelData, pixelData, expectedSize);
    
    // 创建异步工作
    napi_value resourceName;
    napi_create_string_utf8(env, "DetectBlankScreenAsync", NAPI_AUTO_LENGTH, &resourceName);
    
    napi_create_async_work(env, nullptr, resourceName, 
                          ExecuteWork, CompleteWork, 
                          asyncData, &asyncData->work);
    
    // 队列异步工作
    napi_queue_async_work(env, asyncData->work);
    
    OH_LOG_INFO(LOG_APP, "Async work queued successfully");
    
    return promise;
}

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
    OH_LOG_INFO(LOG_APP, "BlankDetector module initialization started");
    
    // 导出异步函数
    napi_property_descriptor desc[] = {
        {"detectBlankScreen", nullptr, DetectBlankScreenAsync, nullptr, nullptr, nullptr, napi_default, nullptr}
    };
    
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    
    // 导出 BlankType 枚举
    napi_value blankTypeEnum;
    napi_create_object(env, &blankTypeEnum);
    
    napi_value whiteScreen, blackScreen, solidColor, loadingFailure, componentError;
    napi_create_int32(env, 0, &whiteScreen);      // WHITE_SCREEN = 0
    napi_create_int32(env, 1, &blackScreen);      // BLACK_SCREEN = 1
    napi_create_int32(env, 2, &solidColor);       // SOLID_COLOR = 2
    napi_create_int32(env, 3, &loadingFailure);   // LOADING_FAILURE = 3
    napi_create_int32(env, 4, &componentError);   // COMPONENT_ERROR = 4
    
    napi_set_named_property(env, blankTypeEnum, "WHITE_SCREEN", whiteScreen);
    napi_set_named_property(env, blankTypeEnum, "BLACK_SCREEN", blackScreen);
    napi_set_named_property(env, blankTypeEnum, "SOLID_COLOR", solidColor);
    napi_set_named_property(env, blankTypeEnum, "LOADING_FAILURE", loadingFailure);
    napi_set_named_property(env, blankTypeEnum, "COMPONENT_ERROR", componentError);
    
    napi_set_named_property(env, exports, "BlankType", blankTypeEnum);
    
    OH_LOG_INFO(LOG_APP, "BlankDetector module initialization completed successfully with HSV support");
    
    return exports;
}
EXTERN_C_END

static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "blankdetector",
    .nm_priv = ((void*)0),
    .reserved = { 0 },
};

extern "C" __attribute__((constructor)) void RegisterBlankDetectorModule(void) {
    OH_LOG_INFO(LOG_APP, "Registering BlankDetector module with HSV support");
    napi_module_register(&demoModule);
}